﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.DirectDraw;
using System.Drawing;

namespace SharpPTCLib
{
    /// <summary>
    /// Implements a DirectDraw video driver
    /// By E.Sandberg, 2009-10-07
    /// </summary>
    class DDrawDriver : IVideoDriver
    {
        private Device _device;
        private Surface _frontSurface;
        private Surface _backSurface;
        private Clipper _clipper;
        private Form _form;
        private int _width;
        private int _height;
        private int _zoom;
        private bool _fullscreen;

        public DDrawDriver()
        {
        }

        public bool Open(string caption, int width, int height, int zoom, bool fullscreen)
        {
            _zoom = zoom;
            _width = width;
            _height = height;
            _fullscreen = fullscreen;
            _form = new Form();
            _form.Text = caption;
            _form.ClientSize = new System.Drawing.Size(_width * _zoom, _height * _zoom);
            _form.FormBorderStyle = FormBorderStyle.FixedSingle;
            _form.MaximizeBox = false;
            _form.Show();

            _device = new Device();
            if (_device == null)
                return false;

            _device.SetCooperativeLevel(_form, CooperativeLevelFlags.Normal);

            /* Create surfaces */
            SurfaceDescription sdesc = new SurfaceDescription();
            sdesc.SurfaceCaps.PrimarySurface = true;
            sdesc.SurfaceCaps.VideoMemory = true;
            _frontSurface = new Surface(sdesc, _device);

            sdesc.SurfaceCaps.PrimarySurface = false;
            sdesc.SurfaceCaps.VideoMemory = false;
            sdesc.SurfaceCaps.OffScreenPlain = true;
            sdesc.Width = _width * _zoom;
            sdesc.Height = _height * _zoom;
            _backSurface = new Surface(sdesc, _device);

            /* Create clipper */
            _clipper = new Clipper(_device);
            _clipper.Window = _form;
            _frontSurface.Clipper = _clipper;
            return true;
        }

        public bool Update(int[] pixel)
        {
            if (_form.IsDisposed)
            {
                return false;
            }

            LockedData ld = _backSurface.Lock(LockFlags.Wait | LockFlags.SurfaceMemoryPointer);
            unsafe
            {
                int* bufPtr = (int*)ld.Data.InternalDataPointer;
                int k = 0;
                int pixp;
                for (int y = 0; y < _height * _zoom; y += _zoom)
                {
                    for (int x = 0; x < _width * _zoom; x += _zoom)
                    {
                        
                        for (int zy = 0; zy < _zoom; zy++)
                        {
                            for (int zx = 0; zx < _zoom; zx++)
                            {
                                pixp = ((y + zy) * _width * _zoom) + x + zx;
                                bufPtr[pixp] = pixel[k];
                            }
                        }
                        k++;
                    }
                }
            }
            _backSurface.Unlock();

            Rectangle rect = _form.RectangleToScreen(_form.ClientRectangle);
            if (!_form.ClientRectangle.Size.IsEmpty)
                _frontSurface.Draw(rect, _backSurface, DrawFlags.Wait);
            
            Application.DoEvents();
            return true;
        }

        public void Close()
        {
            _form.Dispose();
        }
    }
}
